#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/types.h>
#include <ctype.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include "traverse_dir.h"

struct DIR *opendir(const char *dir)
{
    char filespec[_MAX_FNAME];

    strncpy(filespec, dir, _MAX_FNAME);
    char *last = filespec + strlen(filespec) - 1;
    if (*last == '/' || *last == '\\') *last = '\0';
    strcat(filespec,  "/*");

    struct DIR *dp = (struct DIR*)malloc(sizeof(struct DIR));
    dp->offset = 0;
    dp->finished = 0;
    dp->dir = strdup(dir);
    if ((dp->handle = _findfirst(filespec, &(dp->fileinfo))) < 0)
    {
        if (errno == ENOENT)
            dp->finished = 1;
        else
            return NULL;
    }
    return dp;
}

struct dirent* readdir(struct DIR *dp)
{
    if (!dp || dp->finished)
        return NULL;
    if (dp->offset != 0)
    {
        if (_findnext(dp->handle, &(dp->fileinfo)) < 0)
        {
            dp->finished = 1;
            return NULL;
        }
    }
    dp->offset++;
    strncpy(dp->dent.d_name, dp->fileinfo.name, _MAX_FNAME);
    dp->dent.d_ino = 1;
    dp->dent.d_reclen = strlen(dp->dent.d_name);
    dp->dent.d_off = dp->offset;
    return &(dp->dent);
}

void closedir(struct DIR *dp)
{
    if (!dp) return;

    _findclose(dp->handle);

    if(dp->dir) free(dp->dir);

    free(dp);
}

int traverse_dir(string &path, vector<string>& files, const char *ext)
{
    if (path.size() == 0) return -1;

    struct DIR *dir;
    if ((dir = opendir(path.c_str())) == NULL) return -1;

    struct dirent *direntry;
    struct stat st;

    const char last = path[path.size() - 1];

    char temp[256] = {0};
    while ((direntry = readdir(dir)) != NULL)
    {
        if (!strcmp(direntry->d_name,".") || !strcmp(direntry->d_name,".."))
            continue;

        if(last !='/' && last != '\\')
            sprintf(temp,"%s\\%s", path.c_str(), direntry->d_name);
        else
            sprintf(temp,"%s%s", path.c_str(), direntry->d_name);

        if (stat(temp, &st) == 0)
        {
            if((st.st_mode & _S_IFDIR) == _S_IFDIR) continue;

            char drive[MAX_PATH], dir[MAX_PATH], fname[MAX_PATH], _ext[MAX_PATH];
            _splitpath(temp, drive, dir, fname, _ext);
            if (strcmp(_ext+1, ext)) continue;

            files.push_back(temp);
        }
    }
    closedir(dir);
    return (int)files.size();
}
